//
// Created by martin on 8/19/21.
//

#include "threadpool.h"
#include "error.h"

#include <limits.h>
#include <sys/sysinfo.h>
#include <stdio.h>
#include <stdlib.h>

// 线程池实例
static ThreadPool *instance = NULL;

ThreadPool *threadpool_new()
{
    ThreadPool *pool;
    pool = (ThreadPool *)malloc(sizeof(ThreadPool));
    if (!pool) {
        return NULL;
    }

    return pool;
}

/**
 * 初始化线程池
 */
int threadpool_init(ThreadPool *pool, int num)
{
    if (!pool) return -1;
    // 获取CPU个数
    int core_num = get_nprocs_conf();
    // 验证num范围：1 ～ core_num * _POSIX_THREAD_THREADS_MAX
    if (num < 1 || num > _POSIX_THREAD_THREADS_MAX * core_num) return -1;

    pool->thread_nums = num;
    pool->threads = (nThread *)malloc(sizeof(nThread) * num);
    if (!pool->threads) {
        err_sys("create thread array failed");
    }

    // 初始化所有子线程
    int i;
    for (i = 0; i < num; ++i) {
        nthread_init(&pool->threads[i], i + 1);
    }

    pool->last_thread_id = -1;
    return 0;
}

/**
 * main 线程调用，不用考虑线程安全
 */
ThreadPool *threadPool_getInstance()
{
    if (!instance) {
        instance = threadpool_new();
        if (!instance) {
            err_sys("create thread pool failed");
        }
    }

    return instance;
}

/**
 * 线程池将任务按数量均衡派发给各线程，并激活线程
 * @param pool 线程池对象
 * @param task task需要存储在堆中
 * @return 派发结果
 * - -1 失败
 * - 0 成功
 */
int threadpool_dispatchTask(ThreadPool *pool, Task *task)
{
    if (!pool || !task) return -1;
    int id = (pool->last_thread_id + 1) % pool->thread_nums;
    nthread_addTask(&pool->threads[id], task);
    nthread_activate(&pool->threads[id]);
    pool->last_thread_id = id;

    return 0;
}